<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>大屏自动滚动表格组件</title>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }

    body {
      background: linear-gradient(135deg, #1a2a6c, #2c3e50);
      color: #ecf0f1;
      min-height: 100vh;
      padding: 20px;
    }

    .container {
      max-width: 1200px;
      margin: 0 auto;
      padding: 20px;
    }

    header {
      text-align: center;
      margin-bottom: 40px;
      padding: 20px;
      background: rgba(0, 0, 0, 0.3);
      border-radius: 15px;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
    }

    h1 {
      font-size: 2.8rem;
      margin-bottom: 10px;
      background: linear-gradient(90deg, #00c9ff, #92fe9d);
      -webkit-background-clip: text;
      background-clip: text;
      color: transparent;
      text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
    }

    .subtitle {
      font-size: 1.2rem;
      opacity: 0.8;
      max-width: 800px;
      margin: 0 auto;
    }

    .content-wrapper {
      display: flex;
      gap: 30px;
      flex-wrap: wrap;
    }

    .demo-section {
      flex: 1;
      min-width: 300px;
      background: rgba(0, 0, 0, 0.25);
      border-radius: 15px;
      padding: 25px;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
    }

    .docs-section {
      flex: 1;
      min-width: 300px;
      background: rgba(0, 0, 0, 0.25);
      border-radius: 15px;
      padding: 25px;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
    }

    .section-title {
      font-size: 1.8rem;
      margin-bottom: 20px;
      padding-bottom: 10px;
      border-bottom: 2px solid #3498db;
      color: #3498db;
    }

    .control-panel {
      background: rgba(0, 0, 0, 0.2);
      padding: 20px;
      border-radius: 10px;
      margin-bottom: 25px;
    }

    .control-group {
      margin-bottom: 15px;
    }

    label {
      display: block;
      margin-bottom: 8px;
      font-weight: 500;
    }

    input[type="range"] {
      width: 100%;
      height: 8px;
      border-radius: 4px;
      background: #34495e;
      outline: none;
    }

    .btn-group {
      display: flex;
      gap: 10px;
      margin-top: 15px;
    }

    button {
      flex: 1;
      padding: 12px;
      border: none;
      border-radius: 6px;
      background: #3498db;
      color: white;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.3s;
    }

    button:hover {
      background: #2980b9;
      transform: translateY(-2px);
    }

    button:active {
      transform: translateY(1px);
    }

    button.pause {
      background: #e67e22;
    }

    button.pause:hover {
      background: #d35400;
    }

    button.reset {
      background: #e74c3c;
    }

    button.reset:hover {
      background: #c0392b;
    }

    .auto-scroll-table-container {
      height: 400px;
      overflow: hidden;
      border-radius: 10px;
      background: rgba(0, 0, 0, 0.3);
      position: relative;
    }

    .auto-scroll-table {
      width: 100%;
      border-collapse: collapse;
      position: relative;
    }

    .auto-scroll-table thead {
      position: sticky;
      top: 0;
      z-index: 10;
    }

    .auto-scroll-table th {
      background: linear-gradient(180deg, #2980b9, #1a5276);
      color: white;
      padding: 16px 20px;
      text-align: left;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: 0.5px;
    }

    .auto-scroll-table tbody tr {
      border-bottom: 1px solid rgba(255, 255, 255, 0.1);
      transition: background 0.3s;
    }

    .auto-scroll-table tbody tr:hover {
      background: rgba(52, 152, 219, 0.2);
    }

    .auto-scroll-table td {
      padding: 14px 20px;
      color: #ecf0f1;
    }

    .status-indicator {
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 10px;
      background: rgba(0, 0, 0, 0.3);
      border-radius: 5px;
      margin-top: 15px;
      font-size: 0.9rem;
    }

    .status-indicator i {
      margin-right: 8px;
    }

    .status-indicator.running i {
      color: #2ecc71;
    }

    .status-indicator.paused i {
      color: #e67e22;
    }

    .docs-content {
      background: rgba(0, 0, 0, 0.2);
      border-radius: 10px;
      padding: 20px;
      max-height: 500px;
      overflow-y: auto;
    }

    .docs-section h3 {
      margin: 20px 0 10px;
      color: #3498db;
    }

    .prop-table {
      width: 100%;
      border-collapse: collapse;
      margin: 15px 0;
    }

    .prop-table th {
      background: rgba(52, 152, 219, 0.3);
      padding: 10px;
      text-align: left;
    }

    .prop-table td {
      padding: 10px;
      border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    }

    .prop-table tr:last-child td {
      border-bottom: none;
    }

    .code-block {
      background: rgba(0, 0, 0, 0.3);
      padding: 15px;
      border-radius: 8px;
      font-family: monospace;
      margin: 15px 0;
      overflow-x: auto;
      line-height: 1.5;
    }

    .highlight {
      color: #f1c40f;
    }

    footer {
      text-align: center;
      margin-top: 40px;
      padding: 20px;
      opacity: 0.7;
      font-size: 0.9rem;
    }

    @media (max-width: 768px) {
      .content-wrapper {
        flex-direction: column;
      }

      h1 {
        font-size: 2.2rem;
      }
    }
  </style>
</head>

<body>
  <div id="app">
    <div class="container">
      <header>
        <h1><i class="fas fa-table"></i> 大屏自动滚动表格组件</h1>
        <p class="subtitle">专为数据可视化大屏设计的自动滚动表格组件，支持自定义配置和流畅的滚动效果</p>
      </header>

      <div class="content-wrapper">
        <div class="demo-section">
          <h2 class="section-title"><i class="fas fa-laptop-code"></i> 组件演示</h2>

          <div class="control-panel">
            <div class="control-group">
              <label>滚动速度: {{ scrollSpeed }}px/s</label>
              <input type="range" v-model.number="scrollSpeed" min="10" max="100">
            </div>

            <div class="control-group">
              <label>表格行数: {{ tableData.length }}</label>
              <input type="range" v-model.number="dataSize" min="5" max="50">
            </div>

            <div class="btn-group">
              <button @click="toggleScroll" :class="{ pause: !isScrolling }">
                <i :class="isScrolling ? 'fas fa-pause' : 'fas fa-play'"></i>
                {{ isScrolling ? '暂停滚动' : '继续滚动' }}
              </button>
              <button class="reset" @click="resetScroll"><i class="fas fa-sync-alt"></i> 重置位置</button>
            </div>
          </div>

          <div class="auto-scroll-table-container" @mouseenter="pauseScroll" @mouseleave="resumeScroll">
            <auto-scroll-table :data="tableData" :columns="columns" :scroll-speed="scrollSpeed" :paused="!isScrolling"
              @scroll-reset="onScrollReset" header-bg="#1a5276" row-hover-bg="rgba(52, 152, 219, 0.2)"
              stripe-color="rgba(255, 255, 255, 0.05)" height="400px">
              <template #status="{ row }">
                <span :class="['status-badge', row.status]">
                  <i :class="statusIcons[row.status]"></i> {{ row.status }}
                </span>
              </template>
            </auto-scroll-table>
          </div>

          <div class="status-indicator" :class="isScrolling ? 'running' : 'paused'">
            <i :class="isScrolling ? 'fas fa-play-circle' : 'fas fa-pause-circle'"></i>
            当前状态: {{ isScrolling ? '滚动中' : '已暂停' }} | 已滚动距离: {{ scrollDistance }}px
          </div>
        </div>

        <div class="docs-section">
          <h2 class="section-title"><i class="fas fa-book"></i> 组件文档</h2>

          <div class="docs-content">
            <h3>组件封装要点</h3>
            <h4>1.核心功能封装</h4>
            <ul>
              <li>使用CSS transform实现平滑滚动</li>
              <li>通过requestAnimationFrame实现高性能动画</li>
              <li>支持鼠标悬停暂停功能</li>
              <li>无缝循环滚动设计</li>
            </ul>
            <h4>2.可配置参数</h4>
            <ul>
              <li>滚动速度（scrollSpeed）</li>
              <li>表格高度（height）</li>
              <li>暂停状态（paused）</li>
              <li>表头背景（headerBg）</li>
              <li>斑马纹颜色（stripeColor）</li>
              <li>行悬停背景（rowHoverBg）</li>
            </ul>
            <h4>3.插槽系统</h4>
            <ul>
              <li>支持通过插槽自定义列内容</li>
              <li>作用域插槽提供当前行数据</li>
            </ul>
            <h5>4.事件系统</h5>
            <ul>
              <li>scroll-reset事件：当滚动重置时触发</li>
            </ul>

            <h3>组件介绍</h3>
            <p>AutoScrollTable 是一个专为数据可视化大屏设计的自动滚动表格组件，具有以下特点：</p>
            <ul>
              <li>平滑的自动滚动效果</li>
              <li>鼠标悬停暂停滚动</li>
              <li>无缝循环滚动</li>
              <li>高度可定制化</li>
              <li>支持自定义插槽</li>
              <li>响应式设计</li>
            </ul>

            <h3>基本用法</h3>
            <div class="code-block">
              <!-- <code>
                <auto-scroll-table
                  :data="tableData"
                  :columns="columns"
                  scroll-speed="50"
                  height="400px"
                >
                </auto-scroll-table>
              </code> -->
              &lt;auto-scroll-table<br>
              &nbsp;&nbsp;:data="tableData"<br>
              &nbsp;&nbsp;:columns="columns"<br>
              &nbsp;&nbsp;scroll-speed="50"<br>
              &nbsp;&nbsp;height="400px"<br>
              &gt;<br>
              &lt;/auto-scroll-table&gt;
            </div>

            <h3>Props 配置</h3>
            <table class="prop-table">
              <thead>
                <tr>
                  <th>参数</th>
                  <th>说明</th>
                  <th>类型</th>
                  <th>默认值</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td>data</td>
                  <td>表格数据</td>
                  <td>Array</td>
                  <td>[]</td>
                </tr>
                <tr>
                  <td>columns</td>
                  <td>列配置</td>
                  <td>Array</td>
                  <td>[]</td>
                </tr>
                <tr>
                  <td>scroll-speed</td>
                  <td>滚动速度 (px/s)</td>
                  <td>Number</td>
                  <td>40</td>
                </tr>
                <tr>
                  <td>paused</td>
                  <td>是否暂停滚动</td>
                  <td>Boolean</td>
                  <td>false</td>
                </tr>
                <tr>
                  <td>height</td>
                  <td>表格高度</td>
                  <td>String</td>
                  <td>'400px'</td>
                </tr>
                <tr>
                  <td>header-bg</td>
                  <td>表头背景色</td>
                  <td>String</td>
                  <td>'#2980b9'</td>
                </tr>
                <tr>
                  <td>stripe-color</td>
                  <td>斑马纹颜色</td>
                  <td>String</td>
                  <td>'rgba(0,0,0,0.05)'</td>
                </tr>
                <tr>
                  <td>row-hover-bg</td>
                  <td>行悬停背景色</td>
                  <td>String</td>
                  <td>'rgba(0,0,0,0.1)'</td>
                </tr>
              </tbody>
            </table>

            <h3>事件</h3>
            <table class="prop-table">
              <thead>
                <tr>
                  <th>事件名</th>
                  <th>说明</th>
                  <th>回调参数</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td>scroll-reset</td>
                  <td>当滚动到顶部重置位置时触发</td>
                  <td>无</td>
                </tr>
              </tbody>
            </table>

            <h3>插槽</h3>
            <p>使用插槽可以自定义列的内容：</p>
            <div class="code-block">
              &lt;auto-scroll-table :data="data" :columns="columns"&gt;<br>
              &nbsp;&nbsp;&lt;template <span class="highlight">#columnName="{ row }"</span>&gt;<br>
              &nbsp;&nbsp;&nbsp;&nbsp;<span class="highlight">&lt;!-- 自定义内容 --&gt;</span><br>
              &nbsp;&nbsp;&lt;/template&gt;<br>
              &lt;/auto-scroll-table&gt;
            </div>
          </div>
        </div>
      </div>

      <footer>
        <p>© 2023 大屏数据可视化组件库 | 自动滚动表格组件 v1.0</p>
      </footer>
    </div>
  </div>

  <script>
    const { createApp, ref, computed, onMounted, onBeforeUnmount } = Vue;

    // 定义自动滚动表格组件
    const AutoScrollTable = {
      props: {
        data: {
          type: Array,
          default: () => []
        },
        columns: {
          type: Array,
          default: () => []
        },
        scrollSpeed: {
          type: Number,
          default: 40
        },
        paused: {
          type: Boolean,
          default: false
        },
        height: {
          type: String,
          default: '400px'
        },
        headerBg: {
          type: String,
          default: '#2980b9'
        },
        stripeColor: {
          type: String,
          default: 'rgba(0,0,0,0.05)'
        },
        rowHoverBg: {
          type: String,
          default: 'rgba(0,0,0,0.1)'
        }
      },
      setup(props, { emit }) {
        const tableRef = ref(null);
        const scrollPosition = ref(0);
        const animationFrame = ref(null);
        const lastTimestamp = ref(0);
        const rowHeight = 48; // 假设每行高度为48px

        // 计算表格总高度
        const tableHeight = computed(() => {
          return props.data.length * rowHeight;
        });

        // 开始滚动
        const startScroll = (timestamp) => {
          if (!lastTimestamp.value) {
            lastTimestamp.value = timestamp;
          }

          const elapsed = timestamp - lastTimestamp.value;
          lastTimestamp.value = timestamp;

          if (!props.paused) {
            scrollPosition.value += (props.scrollSpeed * elapsed) / 1000;

            // 如果滚动到底部，重置到顶部
            if (scrollPosition.value >= tableHeight.value) {
              scrollPosition.value = 0;
              emit('scroll-reset');
            }

            if (tableRef.value) {
              tableRef.value.style.transform = `translateY(-${scrollPosition.value}px)`;
            }
          }

          animationFrame.value = requestAnimationFrame(startScroll);
        };

        // 初始化滚动
        onMounted(() => {
          animationFrame.value = requestAnimationFrame(startScroll);
        });

        // 组件卸载前清除动画
        onBeforeUnmount(() => {
          if (animationFrame.value) {
            cancelAnimationFrame(animationFrame.value);
          }
        });

        // 重置滚动位置
        const resetScroll = () => {
          scrollPosition.value = 0;
          if (tableRef.value) {
            tableRef.value.style.transform = `translateY(0px)`;
          }
        };

        return {
          tableRef,
          resetScroll
        };
      },
      template: `
        <div class="auto-scroll-table-wrapper" :style="{ height: height, overflow: 'hidden' }">
          <table class="auto-scroll-table" :style="{
            '--header-bg': headerBg,
            '--stripe-color': stripeColor,
            '--row-hover-bg': rowHoverBg
          }">
            <thead>
              <tr>
                <th v-for="(col, index) in columns" :key="index">{{ col.title }}</th>
              </tr>
            </thead>
          </table>
          
          <div class="scroll-container" :style="{ height: height }">
            <table class="auto-scroll-table" ref="tableRef" :style="{
              '--header-bg': headerBg,
              '--stripe-color': stripeColor,
              '--row-hover-bg': rowHoverBg
            }">
              <tbody>
                <tr v-for="(row, rowIndex) in data" :key="rowIndex" :class="{ stripe: rowIndex % 2 === 0 }">
                  <td v-for="(col, colIndex) in columns" :key="colIndex">
                    <slot :name="col.key" :row="row">
                      {{ row[col.key] }}
                    </slot>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      `
    };

    // 创建应用实例
    const app = createApp({
      components: {
        AutoScrollTable
      },
      setup() {
        // 表格列配置
        const columns = [
          { title: 'ID', key: 'id' },
          { title: '项目名称', key: 'name' },
          { title: '负责人', key: 'owner' },
          { title: '截止日期', key: 'deadline' },
          { title: '状态', key: 'status' }
        ];

        // 状态图标映射
        const statusIcons = {
          '进行中': 'fas fa-sync-alt fa-spin',
          '已完成': 'fas fa-check-circle',
          '已延期': 'fas fa-exclamation-circle',
          '未开始': 'fas fa-clock'
        };

        // 生成模拟数据
        const generateData = (count) => {
          const names = ['营销大屏', '数据中台', '用户画像', '风险监控', '实时报表', '运营分析', '业务监控'];
          const owners = ['张明', '李华', '王芳', '赵亮', '刘洋', '陈静', '杨帆'];
          const statuses = ['进行中', '已完成', '已延期', '未开始'];

          return Array.from({ length: count }, (_, i) => ({
            id: i + 1,
            name: `${names[i % names.length]}项目`,
            owner: owners[i % owners.length],
            deadline: `2023-${(i % 12) + 1}-${(i % 28) + 1}`,
            status: statuses[i % statuses.length]
          }));
        };

        // 响应式数据
        const scrollSpeed = ref(40);
        const dataSize = ref(15);
        const isScrolling = ref(true);
        const scrollDistance = ref(0);
        const scrollResetCount = ref(0);

        // 计算表格数据
        const tableData = computed(() => generateData(dataSize.value));

        // 暂停滚动
        const pauseScroll = () => {
          isScrolling.value = false;
        };

        // 继续滚动
        const resumeScroll = () => {
          isScrolling.value = true;
        };

        // 切换滚动状态
        const toggleScroll = () => {
          isScrolling.value = !isScrolling.value;
        };

        // 重置滚动位置
        const resetScroll = () => {
          scrollDistance.value = 0;
        };

        // 监听滚动重置事件
        const onScrollReset = () => {
          scrollResetCount.value++;
        };

        // 模拟滚动距离更新
        setInterval(() => {
          if (isScrolling.value) {
            scrollDistance.value += scrollSpeed.value / 10;
          }
        }, 100);

        return {
          columns,
          tableData,
          scrollSpeed,
          dataSize,
          isScrolling,
          scrollDistance,
          scrollResetCount,
          statusIcons,
          pauseScroll,
          resumeScroll,
          toggleScroll,
          resetScroll,
          onScrollReset
        };
      }
    });

    app.component('AutoScrollTable', AutoScrollTable);
    app.mount('#app');
  </script>
</body>

</html>